/*
kobject使用

安装此模块，将
    1.在/sys/下生成lxz_kobject_name文件夹

卸载此模块，将
    1./sys/lxz_kobject_name文件夹消失

内核预先定义的kobject:
    The global /sys/kernel/ kobject for people to chain off of 
    extern struct kobject *kernel_kobj;

    The global /sys/kernel/mm/ kobject for people to chain off of 
    extern struct kobject *mm_kobj;

    The global /sys/hypervisor/ kobject for people to chain off of 
    extern struct kobject *hypervisor_kobj;

    The global /sys/power/ kobject for people to chain off of 
    extern struct kobject *power_kobj;
    
    The global /sys/firmware/ kobject for people to chain off of
    extern struct kobject *firmware_kobj;
*/

#include "linux/init.h"
#include "linux/module.h"
#include "linux/kobject.h"
#include "linux/slab.h"

static const char *lxz_kobject_name = "lxz_kobject_name";
static struct kobject *lxz_kobject = NULL;

static int __init lxz_kobject_init(void)
{
    struct kset *kset = NULL; // lxz_kobject所属的kset
    char *path = NULL;

    printk("file=%s,fun=%s,line=%d\n", __FILE__, __FUNCTION__, __LINE__);

    lxz_kobject = kobject_create_and_add(lxz_kobject_name, NULL);
    if (!lxz_kobject)
    {
        printk("kobject_create_and_add error\n");
        return -1;
    }
    printk("kobject_create_and_add succeed\n");

    printk("lxz_kobject->name=%s", lxz_kobject->name);

    if (list_empty_careful(&(lxz_kobject->entry)))
    {
        printk("lxz_kobject list_empty_careful\n");
    }

    if (lxz_kobject->parent)
    {
        printk("lxz_kobject->parent->name=%s", lxz_kobject->parent->name);
    }

    // 获取所属的kset
    kset = to_kset(lxz_kobject);
    if (!kset)
    {
        printk("to_kset error\n");
    }
    else
    {
        printk("to_kset succeed\n");
        printk("kset->kobj.name=%s\n", kset->kobj.name); // kset->kobj.name=lxz_kobject_name
    }

    if (lxz_kobject->ktype)
    {
        printk("lxz_kobject->ktype\n");
    }

    path = kobject_get_path(lxz_kobject, GFP_KERNEL);
    if (path)
    {
        printk("kobject_get_path is %s\n", path);

        kfree(path);
    }

    return 0;
}

static void __exit lxz_kobject_exit(void)
{
    printk("file=%s,fun=%s,line=%d\n", __FILE__, __FUNCTION__, __LINE__);

    if (lxz_kobject)
    {
        kobject_del(lxz_kobject);
        lxz_kobject = NULL;
    }
}

module_init(lxz_kobject_init);
module_exit(lxz_kobject_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("lxz");
